package peace.gui.controls.text
{
import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.FocusEvent;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.events.TextEvent;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFieldType;
import flash.text.TextFormat;

import peace.gui.controls.Control;
import peace.gui.controls.scroll.Scrollbar;

/**
* 
*/
[Event(name="change", type="flash.events.Event")]
/**
* 
*/
[Event(name="textInput", type="flash.events.TextEvent")]
/**
 * 
 */
public class InputField extends Control
{
	/**
	 * открываю текстовое поле чтобы не делегировать API <br>
	 * 
	 * Для операций, дублированных в InputField (например, изменений размеров), нужно пользоваться InputField API
	 */
	public var textField:TextField = new Text();
	/**
	 * 
	 */
	protected static const DEFAULT_WIDTH:int = 100;
	/**
	 * 
	 */	
	protected static const DEFAULT_TEXT_FORMAT:TextFormat = new TextFormat("Arial", 12);
	/**
	 * 
	 */	
	protected var bar:Scrollbar;
	/**
	 * 
	 */	
	protected var skin:Skin;
	/**
	 * 
	 */	
	protected var multiline:Boolean;
	
	/**
	 * 
	 * @param textFormat
	 * @param multiline
	 * @param scrollPane
	 * @param blurSkin
	 * @param focusSkin
	 * 
	 */	
	public function InputField (textFormat:TextFormat = null, 
								multiline:Boolean = false,
								scrollbar:Scrollbar = null,
								blurSkin:DisplayObject = null, 
								focusSkin:DisplayObject = null)
	{
		super();
		
		
		this.multiline = multiline;
		
		if (multiline)
		{
			bar = scrollbar || new Scrollbar();
		}
		
		setSkin(blurSkin, focusSkin);
		this.textFormat = textFormat || DEFAULT_TEXT_FORMAT;
		
		init();
	}
	/**
	 * 
	 * 
	 */	
	private function init():void
	{
		addChild(skin.focus);
		skin.focus.visible = false;
		addChild(skin.blur);

		textField.type = TextFieldType.INPUT;
		textField.background = false; 
		textField.border = false;
		
		if (multiline)
		{
			textField.multiline = textField.wordWrap = true;
			addChild(textField);
			
			bar.scrollStep = textField.getLineMetrics(0).height;
			bar.content = textField;
			addChild(bar);
			
			// обрабатываем родную перемотку текста мышкой
			textField.addEventListener(Event.SCROLL, onTextScrolled, false,0,true);
			
			width = DEFAULT_WIDTH;
			height = 100;
			
			// ради проверки на видимость
			onTextScrolled(null);
		}
		else
		{
			var h:Number;
			textField.text = "sometext";
			textField.autoSize = TextFieldAutoSize.LEFT;
			h = textField.textHeight + 4;
			textField.autoSize = TextFieldAutoSize.NONE;
			textField.text = "";
			
			addChild(textField);
			
			width = DEFAULT_WIDTH;
			height = h;
		}
		
		
		textField.addEventListener(FocusEvent.FOCUS_IN, onFocus, false,0,true);
		textField.addEventListener(FocusEvent.FOCUS_OUT, onFocus, false,0,true);
		
		// локализуем колесо мышки внутри контрола 
		textField.addEventListener(MouseEvent.MOUSE_WHEEL, onMouseWheel, false,0,true); 
		// локализуем клавиатуру внутри контрола 
		textField.addEventListener(KeyboardEvent.KEY_DOWN, onKeyboard, false,0,true); 
	}
	/**
	 * 
	 * @param value String
	 * 
	 */		
	public function set text (value:String):void
	{
		textField.text = value;
	}
	/**
	 * 
	 * @return 
	 * 
	 */
	public function get text ():String
	{
		return textField.text;
	}
	/**
	 * 
	 * @param value String
	 * 
	 */		
	public function set htmlText (value:String):void
	{
		textField.htmlText = value;
	}
	/**
	 * 
	 * @return 
	 * 
	 */
	public function get htmlText ():String
	{
		return textField.htmlText;
	}
	/**
	 * 
	 * @return 
	 * 
	 */	
	override public function get value():*
	{
		return textField.text;
	}
	/**
	 * 
	 * @param v
	 * 
	 */	
	override public function set value(v:*):void
	{
		textField.text = v ? String(v) : "";
	}
	/**
	 * 
	 * @param value TextFormat
	 * 
	 */	
	public function set textFormat (value:TextFormat):void
	{
		textField.setTextFormat(value);
		textField.defaultTextFormat = value;
	}
	public function get textFormat ():TextFormat
	{
		return textField.defaultTextFormat;
	}
	/**
	 * 
	 * @param b Boolean
	 * 
	 */	
	public function set password (b:Boolean):void
	{
		textField.displayAsPassword = b;
	}
	/**
	 * 
	 * @param blurSkin
	 * @param focusSkin
	 * 
	 */	
	public function setSkin (blurSkin:DisplayObject, focusSkin:DisplayObject):void
	{
		var hasFocus:Boolean = skin ? skin.focus.visible : false;
		
		if (skin)
		{
			removeChild(skin.focus);
			removeChild(skin.blur);
		}
		
		skin = new Skin(blurSkin, focusSkin);
		
		addChildAt(skin.focus, 0);
		addChildAt(skin.blur, 0);
		skin.focus.width = skin.blur.width = width;
		skin.focus.height = skin.blur.height = height;
		focus(hasFocus);
	}
	/**
	 * 
	 * @param value
	 * 
	 */
	override public function set width(value:Number):void
	{
		skin.blur.width = skin.focus.width = value;
		
		textField.width = multiline ? value - bar.width : value;
		
		if (multiline) bar.x = value - bar.width;
	}
	/**
	 * 
	 * @param value
	 * 
	 */
	override public function set height(value:Number):void
	{
		skin.blur.height = skin.focus.height = value;
		
		textField.height = value;
		
		if (multiline)
		{
			bar.size = value;
		}
	}
	/**
	 * Переопределяем так как при наличии картинок в тексте высота возвращается не верно 
	 * 
	 * @return 
	 * 
	 */	
	override public function get height():Number
	{
		return Text(textField).bounds.height;
	}
	/**
	 * 
	 * @param e
	 * 
	 */
	private function onTextScrolled (e:Event):void
	{
		var delta:Number = (textField.textHeight - height) / (textField.maxScrollV - 1);
		
		if (delta <= 0)
		{
			bar.visible = false;
			return;
		}
		else
		{
			var scrollpos:int = bar.scrollPosition / delta;
			
			if (scrollpos != textField.scrollV - 1)
			{
				bar.scrollPosition = (textField.scrollV - 1) * delta;
			}
			
			bar.visible = true;
		}
		
	}
	/**
	 * 
	 * @param e
	 * 
	 */	
	private function onFocus (e:FocusEvent):void
	{
		focus(e.type == FocusEvent.FOCUS_IN);
	}
	/**
	 * 
	 * @param e
	 * 
	 */	
	private function onMouseWheel (e:MouseEvent):void
	{
		if (multiline && bar.visible)
		{
			e.stopPropagation();
		}
	}
	/**
	 * 
	 * @param e
	 * 
	 */
	private function onKeyboard (e:KeyboardEvent):void
	{
		e.stopImmediatePropagation();
	}
	/**
	 * 
	 * @param b
	 * 
	 */	
	private function focus (b:Boolean):void
	{
		skin.focus.visible = b;
		skin.blur.visible = !b;
	}
	
}
}
	import flash.text.TextField;
	import flash.geom.Rectangle;
	
/**
 * модифицированное поле для наёбок Скроллпейна 
 */
internal class Text extends TextField
{
	/**
	 * кешируем часть данных о размерах и положении 
	 */
	public var bounds:Rectangle = new Rectangle();
	/**
	 * Кешируем высоту, тк при наличии картинок (после загрузки) TextField::height меняется
	 * 
	 * @param value
	 * 
	 */	
	override public function set height(value:Number):void
	{
		bounds.height = value;
		super.height = value;
	}
	/**
	 * хотим чтобы скроллер реагировал на реальное изменение размеров текста а не поля
	 *  
	 * @return 
	 * 
	 */	
	override public function get height():Number
	{
		return Math.max(textHeight, bounds.height);
	}
	/**
	 * 
	 * @param value
	 * 
	 */	
	override public function set y(value:Number):void
	{
		bounds.y = value;
		
		var delta:Number = (textHeight - bounds.height) / (maxScrollV - 1);
		scrollV = int(- value/delta) + 1;
	}
	/**
	 * 
	 * @return 
	 * 
	 */
	override public function get y():Number
	{
		return bounds.y;
	}
}


import flash.display.DisplayObject;
import flash.display.Shape;
	
/**
 * 
 */
internal class Skin
{
	public var focus:DisplayObject;
	public var blur:DisplayObject;
	
	public function Skin (blurSkin:DisplayObject, focusSkin:DisplayObject)
	{
		focus = focusSkin || getFocusSkin();
		blur = blurSkin || getBlurSkin();
	}
	
	private function getFocusSkin ():DisplayObject
	{
		var s:Shape = new Shape();
		s.graphics.lineStyle(0,0x000000);
		s.graphics.beginFill(0xffffff);
		s.graphics.drawRect(0,0,10,10);
		return s;
	}
	
	private function getBlurSkin ():DisplayObject
	{
		var s:Shape = new Shape();
		s.graphics.lineStyle(0,0x999999);
		s.graphics.beginFill(0xffffff);
		s.graphics.drawRect(0,0,10,10);
		return s;
	}
	
	
}